<?php
// 应用公共文件
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use think\facade\Db; // 数据库的链
use malkusch\lock\mutex\PHPRedisMutex;
/**
 * 上级分销 如果有bug 请同时修改计划任务中的方法
 * @param $uid  当前用户id
 * @param $profit  奖励金牌数
 * @param $type  奖励类型 0银牌 1金牌
 * @param string $text 奖励说明
 * @return void
 */
function getMiningProfitByParent($uid,$profit,$type,$text='团队奖励')
{
        // 查询上级
        $sid = Db::name('user')->where('id',$uid)->value('sid');
        
        if(!$sid || $sid == 0){
            return;
        }
        
        $i = 1;// uid用户的第几个上级

        // 获取配置信息
        $config = getSetting('config');
        $tuan = $config['tuan']; // 团队奖励比例
        
        $k = 0;

        do {
            // 查询上级的上级
            $parent = Db::name('user')->where('id', $sid)->find();
            // // $i < 2 是直推 和 间推
            if($i <= 2){
                if($i == 1){
                    // 给直推上级分佣 direct
                    // 计算直推奖励 保留2位小数
                    $direct_profit = round($profit * $config['direct'] / 100, 2);
                    // 给直推上级分佣
                    userRecord($parent['id'], $direct_profit, $type, 0, '直推奖励:'. $text.'来自用户ID:'. $uid ."收益百分百". $config['direct']."%");
                }else{
                    // 给间推上级分佣 indirect
                    // 计算间推奖励 保留2位小数
                    $indirect_profit = round($profit * $config['indirect'] / 100, 2);
                    // 给间推上级分佣
                    userRecord($parent['id'], $indirect_profit, $type, 0, '间推奖励:'. $text.'来自用户ID:'. $uid."收益百分百". $config['indirect']."%");
                }
            }else{
                // ================== 2级以外的分销 =========================== 最高10级
                // 判断是否为0撸用户 查询闪卡使用中并且未到期 0撸用户不参3代以为的分销
                // 查询用户的闪卡情况
                $flash_card = Db::name('user_card_record')->where('uid', $uid)->where('is_status', 1)->where('del', '=', 0)->find();
                // $flash_card = 1;测试使用
                // 闪卡存在并且未到期
                if($flash_card){
                    // 在查看用户的足球数量
                    $football = Db::name('ball_user')->where('uid', $uid)->where('is_status', 0)->count();
                    // $football = $parent['football']; // 测试使用
                    /**
                     * 由于业务逻辑特殊 5级 和 9级 的足球数量需要加 1
                     */
                    $football_num = 0;
                    if($i == 6 || $i == 10){
                        $football_num = 1;
                    }
                     // 3,4,6,7,8,10级 足球数量条件不加 1
                    if($football >= $tuan[$k - $football_num]['generation']){
                        // 计算奖励 保留2位小数
                        $generation_profit = round($profit * $tuan[$k - $football_num]['ratio'] / 100, 2);
                        // 给上级分佣
                        userRecord($parent['id'], $generation_profit, 1, 0, '第'. $i . '代奖励:'. $text.'来自用户ID:'. $uid."收益百分百:".$tuan[$k - $football_num]['ratio']."%");
                    }
                    if($football_num == 0){
                        $k++;
                    }
                }
            }

            // 给sid 分配最新上级
            $i++;
            $sid = $parent['sid'];
        }while($sid > 0 && $i < 11); // 最高10级 $i小于11 就是10级
    }

/**
 * 闪卡赠送
 * @param int $uid 用户id
 * @param int $card_id 闪卡id
 * @param int $num 数量
 * @param string $remarks 备注
 * @return bool
 */
function flashCardSend($uid, $card_id, $num, $remarks)
{
    $user = Db::name('user')->where('id', $uid)->find();
    if (!$user) {
        return array('code' => 500,'msg' => '用户不存在');
    }
    $flash_card = Db::name('card')->where('id', $card_id)->find();
    if (!$flash_card) {
        return array('code' => 500,'msg' => '闪卡不存在');
    }
    $redis = new \Redis();
    $redis->connect("localhost");
    $mutex = new PHPRedisMutex([$redis], "user_flashCardSend_".$uid);
    return $mutex->synchronized(function () use ($uid, $card_id,$num, $remarks){
        // 开启事务
        
            Db::startTrans();
            try {
                for($i=0; $i <$num; $i++){
                    $data = [
                        'uid' => $uid,
                        'cid' => $card_id,
                        'profit_day' => 0,
                        'is_status' => 0,
                        'obtain_time' => time(),
                        'remarks' => $remarks,
                    ];
                
                    Db::name('user_card_record')->insert($data);
                }
                // 提交事务
                Db::commit();
                return array('code' => 200,'msg' => '闪卡赠送成功');

            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                return array('code' => 500,'msg' => '闪卡赠送失败');
            }
        
        // 结束事务
    });
}

/**
 * 获取设置的配置
 */
function getSetting($name)
{
    // 获取set表
    $set = Db::name('set')->where('id', 1)->value($name);
    // set 转数组
    $set = json_decode($set, true);
    return $set;
}
/**
 * 生成订单号
 * @param string $type 订单类型
 * @return string
 */
function ordersn($type)
{
    $osn = date('Ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
    return $type.$osn;
}

/**
 * 资金操作记录到user_record表 如果有bug 请同时修改计划任务中的方法
 * @param int $uid 用户id
 * @param string $amount 金额数量
 * @param string $recharge_type 类型 0 银牌 1 金牌
 * @param string $operation_type 操作类型 0 充值 1扣除
 * @param string $remarks 描述
 * @return bool
 */
function userRecord($uid, $amount,$recharge_type, $operation_type,  $remarks)
{

    $user = Db::name('user')->where('id', $uid)->find();
    if (!$user) {
        return array('code' => 500,'msg' => '用户不存在');
    }
    $type = 'silver'; // 默认银牌
    if($recharge_type == 1){
        $type = 'gold'; // 金牌
    }

    if ($operation_type == 0) {
        $new_amount = bcadd($user[$type], $amount, 2);
    } else {
        if($user[$type] < $amount){
            return array('code' => 500,'msg' => '余额不足');
        }
        $new_amount = bcsub($user[$type], $amount, 2);
    }
    $redis = new Redis();
    $redis->connect("localhost");
    $mutex = new PHPRedisMutex([$redis], "user_record_".$uid);
    return $mutex->synchronized(function () use ($uid, $recharge_type, $operation_type, $amount, $new_amount,$remarks,$type,$user){
        // 开启事务操作
        Db::startTrans();
        try {
            $data = [
                'uid' => $uid,
                'order_sn' => ordersn("FD"),
                'recharge_type' => $recharge_type,
                'operation_type' => $operation_type,
                'ago_amount' => $user[$type],
                'after_amount' => $new_amount,
                'amount' => $amount,
                'remarks' => $remarks,
                'addto_time' => time(),
            ];
            Db::name('user_record')->insert($data);
            Db::name('user')->where('id', $uid)->update([$type => $new_amount]);
            // 提交事务
            Db::commit();
            return array('code' => 200,'msg' => '资金操作成功');
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return array('code' => 500,'msg' => '操作失败');
        }
        // 结束事务
    });
    

}

function createToken($uid, $pass = '', $ip = '')
{
    $nowTime = time();
    try {
        $token['aud'] = ''; //接收该JWT的一方，可选
        $token['iat'] = $nowTime; //签发时间
        // 设置token过期时间为7天
        $token['exp'] = $nowTime + 60 * 60 * 24 * 1000;
        $token['UserID'] = $uid;
        $token['ip'] = $ip;
        $token['pass'] = $pass;
        $token['iss'] = 'machines';
        $token['sub'] = "user token";
        $json = JWT::encode($token, 'a_secret_token', "HS256");
        return $json;
    } catch (\Firebase\JWT\ExpiredException $e) { //签名不正确
        $returndata['code'] = "104";
        $returndata['msg'] = $e->getMessage();
        $returndata['data'] = "";
        return json_encode($returndata);
    } catch (\Exception $e) { //其他错误
        $returndata['code'] = "199";
        $returndata['msg'] = $e->getMessage();
        $returndata['data'] = "";
        return json_encode($returndata);
    }
}
/**
 * 验证token是否有效
 * @param string $jwt 需要验证的token
 */
function checkToken($jwt = '')
{
    try {
        JWT::$leeway = 60; //当前时间减去60，把时间留点余地
        $decoded = JWT::decode($jwt, new Key('a_secret_token', 'HS256')); //HS256方式，这里要和签发的时候对应
        $arr = (array)$decoded;
        $returndata['code'] = "200";
        $returndata['msg'] = "成功";
        $returndata['data'] = $arr;
        return $returndata;
    } catch (\Firebase\JWT\SignatureInvalidException $e) {
        $returndata['code'] = "101";
        $returndata['msg'] = $e->getMessage();
        $returndata['data'] = "";
        return $returndata;
    } catch (\Firebase\JWT\BeforeValidException $e) {
        $returndata['code'] = "102";
        $returndata['msg'] = $e->getMessage();
        $returndata['data'] = "";
        return $returndata;
    } catch (\Firebase\JWT\ExpiredException $e) {
        $returndata['code'] = "103";
        $returndata['msg'] = $e->getMessage();
        $returndata['data'] = "";
        return $returndata;
    } catch (\Exception $e) {
        $returndata['code'] = "199";
        $returndata['msg'] = $e->getMessage();
        $returndata['data'] = "";
        return $returndata;
    }
}
/**
 * 根据地址转换经纬度
 */
function getLngLat($address)
{
    $key = '3BKBZ-WDGKL-332PW-EWKOS-CXYEJ-KPBOZ';
    $url = 'http://apis.map.qq.com/ws/geocoder/v1/?address=' . $address . '&key=' . $key;
    $ch = curl_init(); /*设置url传输选项*/
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); /*执行url会话*/
    $data = curl_exec($ch);
    $map = json_decode($data);
    var_dump($map);
    $location = $map->result->location; /*经度*/

    return array(
        'lng' => $location->lng,
        'lat' => $location->lat,
    );
}
function AppsendMsg($uid, $title, $content)
{
    // 改成你自己的云函数地址
    $url = 'https://fc-mp-423f54df-ee81-4189-b5ed-e378ce97439f.next.bspapp.com/';
    $data = [
        'push_clientid' => $uid,
        'title' => $title,
        'content' => $content,
        'payload' => '{"text":"体验一下uni-push2.0"}'
    ];
    $rs = httpcurl($url, json_encode($data), true, true);
    $rs = json_decode($rs, true);
    if ($rs['errCode'] == 0) {
        return json(['code' => 200, 'message' => '发送成功']);
    } else {
        return json(['code' => $rs['errCode'], 'message' => $rs['errMsg']]);
    }
}

/**
 * @param string $url 请求网址
 * @param bool $params 请求参数
 * @param bool $post 请求方式，是否是post
 * @param bool $https 请求http协议，是否是https
 * @return bool|mixed
 */
function httpcurl($url, $params = false, $post = false, $https = false)
{
    $httpInfo = array();
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36');
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    if ($post === true) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        //            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
        curl_setopt($ch, CURLOPT_URL, $url);
    } else {
        if ($params === false) {
            curl_setopt($ch, CURLOPT_URL, $url);
        } else {
            if (is_array($params)) {
                $params = http_build_query($params);
            }
            curl_setopt($ch, CURLOPT_URL, $url . '?' . $params);
        }
    }

    if ($https === true) {
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
    }
    $response = curl_exec($ch);
    // if ($response === false) {
    //     Illuminate\Support\Facades\Log::error(sprintf('curl 错误。 url:%s, error:%s', $url, curl_error($ch)));
    //     return false;
    // }
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $httpInfo = array_merge($httpInfo, curl_getinfo($ch));
    curl_close($ch);
    return $response;
}
